/**
 * keyof typeof 签名索引类型使用实例
 */
type TagName = keyof HTMLElementTagNameMap;
function createElement<T extends TagName>(
  tagName: T
): HTMLElementTagNameMap[T] {
  return document.createElement(tagName);
}

/**
 * in操作符
 */
type Foo = {
  [key in "a" | "b"]: string;
};
let foo: Foo = {
  a: "a",
  b: "b",
};

type User = {
  readonly id: number;
  name: string;
  age: number;
};

type UserKeys = keyof User;

// type UserCopy = {
//   [key in UserKeys]: User[key];
// };
// let userC: UserCopy = {
//   id: 1,
//   name: "ss",
//   age: 1,
// };
// userC.id = 1; // 只读属性并没有赋值过来

type UserCopy = {
  [key in keyof User]: User[key];
};
let userC: UserCopy = {
  id: 1,
  name: "ss",
  age: 1,
};
// userC.id = 1; // 只读属性被赋值过来了！！！

type Copy<T extends object> = {
  [K in keyof T]: T[K];
};
const u2: Copy<User> = {
  id: 1,
  name: "name",
  age: 1,
};
// u2.id = 122; // 只读属性被赋值过来了！！！

type A = keyof any; // type A = string | number | symbol
type AA = keyof any & string; // 联合类型加交叉类型会得到交叉类型的结果。type AA = string;
/**
 * 但是对 Copy进行[K in keyof T & string]:T[K] 使用后会破坏readonly和可选的限制。
 */
type Person = {
  name: string;
  age: number;
  sex: string;
};
type ValueType = Person["sex" | "age"]; // string | number
export {};
